
#ifndef __MY_SVC_H__
#define __MY_SVC_H__

#include "stdint.h"
#include "stdio.h"
#include "stdbool.h"


void test_array_fuzhi(void);

#ifdef SVCALL_AS_NORMAL_FUNCTION
#define SVCALL(number, return_type, signature) return_type signature
#else

#ifndef SVCALL
#if defined (__CC_ARM)
#define SVCALL(number, return_type, signature) return_type __svc(number) signature
#elif defined (__GNUC__)
#ifdef __cplusplus
#define GCC_CAST_CPP (uint8_t)
#else
#define GCC_CAST_CPP    
#endif
#define SVCALL(number, return_type, signature)          \
  _Pragma("GCC diagnostic push")                        \
  _Pragma("GCC diagnostic ignored \"-Wreturn-type\"")   \
  __attribute__((naked))                                \
  __attribute__((unused))                               \
  static return_type signature                          \
  {                                                     \
    __asm(                                              \
        "svc %0\n"                                      \
        "bx r14" : : "I" (GCC_CAST_CPP number) : "r0"   \
    );                                                  \
  }                                                     \
  _Pragma("GCC diagnostic pop")
  
#elif defined (__ICCARM__)
#define PRAGMA(x) _Pragma(#x)
#define SVCALL(number, return_type, signature)          \
PRAGMA(swi_number = (number))                           \
 __swi return_type signature;
#else
#define SVCALL(number, return_type, signature) return_type signature  
#endif
#endif  // SVCALL

#endif  // SVCALL_AS_NORMAL_FUNCTION

/*
在RVDS和Keil RVMDK中，为了方便我们放参数，提供了“ __svc”编译器指示字。
举例来说，如果需要在3号服务请求中传递4个参数，则可以类似下例写：
unsigned long __svc(0x03) CallSvc3(unsigned long svc_r0, unsigned long svc_r1, unsigned long svc_r2, unsigned long svc_r3);
当C程序调用这种函数时，则编译器会自动生成SVC指令，如下所示：
int Func(void)
{
unsigned long p0, p1, p2, p3; //传递给SVC服务例程的4个函数
unsigned long svcRet; //系统服务的返回值
. . .
svcRet=CallSvc3(p0, p1, p2, p3); // 呼叫3号系统服务，并且传递4个参数，依次为：
p1,p2,p3,p4，再接收返回值到svcRet中（别忘了，这个返回值的来历不寻常）
. . .
return;
}
如欲获知__svc的官方说明，可以查阅《 RVCT 3.0 Compiler and Library Guide(Ref6)》。
如果使用的是GNU的工具链，里面没有__svc关键字。但是GCC支持内联汇编，可以实现
此功能。例如，如果需要呼叫3号系统服务，同时传递一个参数，还接收一个返回值（两者
都通过R0），则可以使用如下的内联汇编来呼叫SVC：
int MyDataIn ＝ 0x123;
__asm __volatile (”mov R0, %0\n”
”svc 3 \n” : ”” : ”r” (MyDataIn) );
上段内联汇编码中，两个“：”后面分别对应输入数据——由r(MyDataIn)指定，以及输
出数据——即上段代码中是””，语法模式如下所示：
__asm ( assembler_code : output_list : input_list )
在第19章中，给出了使用GNU工具链的更多汇编例子。如欲获取有关内联汇编的详细信
息，还请参阅GNU工具链的说明文档。
*/

#endif //__MY_SVC_H__
